#ifndef __SINGAPOREBUSITERATORSVIEW__
#define __SINGAPOREBUSITERATORSVIEW__

// [[[ begin generated region: do not modify [Generated Includes]
#include <aknview.h>
// ]]] end generated region [Generated Includes]

#include <AknsControlContext.h>
#include <AknsBasicBackgroundControlContext.h>
#include <akntitle.h>
#include "googlepositioning.h"
#include "positionrequest.h"
#include "SingaporeBusStructures.h"
#include "AsyncFileLoader.h"
#include "IteratorControl.h"
#include "FunTrace.h"
#include "Binder.h"
#include "SingaporeBusDocument.h"

template<class T>
class CSingaporeBusIteratorView : public CAknView
	{
	
public:

	
	
	struct CContainer : public CCoeControl, public MCoeControlBackground
		{
		public:
		LManagedPtr< CAknsBasicBackgroundControlContext > iBgContext;
		CIteratorControl<T>* iIteratorControl; // automatically deleted because it is a child control (not 100% sure of the reason but it is auto deleted)
		CEikLabel* iPositionLabel;
		CEikLabel* iTitleLabel;
	    LManagedPtr< scalp::CFunction<TKeyResponse (const TKeyEvent&,TEventCode)> > iOfferKeyEventFun;
	    LManagedPtr< scalp::CFunction<TBool (const TPointerEvent& aPointerEvent)> > iHandlePointerEventFun;
	    CAknView* iView;
	    
		void ConstructL(scalp::CFunction<CEikListBox* ()>* aListBoxFun, CAknView* aView)
			{
			TFunTrace funTrace(__PRETTY_FUNCTION__);
			LCleanedupPtr< scalp::CFunction<CEikListBox* ()> > listBoxFun(aListBoxFun);
			CreateWindowL();
			InitComponentArrayL();
			iView = aView;
			TRect viewClientRect = iView->ClientRect();
			iBgContext = CAknsBasicBackgroundControlContext::NewL( KAknsIIDQsnBgAreaMain, 
														viewClientRect, 
														ETrue );
			iIteratorControl = new (ELeave) CIteratorControl<T>();
			Components().AppendLC(iIteratorControl);
			CleanupStack::Pop();
			iIteratorControl->ConstructL(
					TRect(0, 0, viewClientRect.Width(), viewClientRect.Height()),
					(*listBoxFun)(),
					this,
					aView->Id().iUid);
			
			
			if(1==0)
			{
			iPositionLabel = new (ELeave) CEikLabel;
			Components().AppendLC(iPositionLabel);
			CleanupStack::Pop();
			iPositionLabel->SetRect( TRect(0, 50, viewClientRect.Width(), 75) );
			iPositionLabel->SetMopParent(this);
			iPositionLabel->SetContainerWindowL(*this);
			iPositionLabel->OverrideColorL( EColorLabelTextEmphasis, KRgbBlue );
			iPositionLabel->SetEmphasis( CEikLabel::EPartialEmphasis ); 
			iPositionLabel->SetBrushStyle( CWindowGc::ENullBrush );
			iPositionLabel->SetTextL(_L("Position"));
			}
			{
			iTitleLabel = new (ELeave) CEikLabel;
			Components().AppendLC(iTitleLabel);
			CleanupStack::Pop();
			iTitleLabel->SetMopParent(this);
			iTitleLabel->SetContainerWindowL(*this);
			MAknsSkinInstance* skin = AknsUtils::SkinInstance();
			TRgb textColor;
			AknsUtils::GetCachedColor( skin, textColor, KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG9 );
			//AknsUtils::GetCachedColor( skin, iGridTextHColor, KAknsIIDQsnTextColors, EAknsCIQsnTextColorsCG11 );
			iTitleLabel->OverrideColorL( EColorLabelTextEmphasis, textColor );
			iTitleLabel->SetEmphasis( CEikLabel::EPartialEmphasis ); 
			iTitleLabel->SetBrushStyle( CWindowGc::ENullBrush );	
			iTitleLabel->SetTextL(_L("Title"));
			}
			SetRect(viewClientRect);
			ActivateL();
			}

		//http://www.developer.nokia.com/Community/Wiki/Drawing_skins_in_container
		TTypeUid::Ptr MopSupplyObject(TTypeUid aId)
			{
			TFunTrace funTrace(__PRETTY_FUNCTION__);
		    if ( aId.iUid == MAknsControlContext::ETypeId && iBgContext.Get()) 
		        { 
		        return MAknsControlContext::SupplyMopObject( aId, iBgContext.Get() );
		        }
		    return CCoeControl::MopSupplyObject( aId );
		    }
		
		// from MCoeControlBackground
		void Draw(CWindowGc& aGc, const CCoeControl& aControl, const TRect& aRect) const
		{
			if(iBgContext.Get())
			{
				AknsDrawUtils::Background(AknsUtils::SkinInstance(),
				iBgContext.Get(), 
				this, 
				aGc,
				aRect
				);
			}
		}
		
		
		
		//http://www.developer.nokia.com/Community/Wiki/CS001438_-_Listening_for_screen_orientation_changes
		void HandleResourceChange(TInt aType)
			{
			TFunTrace funTrace(__PRETTY_FUNCTION__);
			CCoeControl::HandleResourceChange(aType);
			SetRect(iView->ClientRect());
			}

		/*
		void Draw( const TRect& aRect ) const
		{
			CWindowGc& gc = SystemGc();
		    gc.SetBrushStyle( CGraphicsContext::ESolidBrush );
		    MAknsSkinInstance* skin = AknsUtils::SkinInstance();
		    MAknsControlContext* cc = AknsDrawUtils::ControlContext( this );
		    AknsDrawUtils::Background( skin, cc, this, gc, aRect );
		}*/	
		
	    TKeyResponse OfferKeyEventL(const TKeyEvent& aKeyEvent,TEventCode aType)
	    	{
	    	TFunTrace funTrace(__PRETTY_FUNCTION__);
	    	if(iOfferKeyEventFun && (*iOfferKeyEventFun)(aKeyEvent, aType) == EKeyWasConsumed )
	    		return EKeyWasConsumed;
	    	return iIteratorControl->OfferKeyEventL(aKeyEvent, aType);
	    	}
		
	    void HandlePointerEventL(const TPointerEvent& aPointerEvent)
	    	{
	    	TFunTrace funTrace(__PRETTY_FUNCTION__);
	    	if(!iHandlePointerEventFun || !(*iHandlePointerEventFun)(aPointerEvent))
	    		CCoeControl::HandlePointerEventL(aPointerEvent);
	    	}
		
		void SizeChanged()
			{
			TFunTrace funTrace(__PRETTY_FUNCTION__);
			CCoeControl::SizeChanged();
			if(iIteratorControl)
				{
				TInt titleHeight = 0;
				 //TInt titleHeight = Max(15, (Rect().Height() % iIteratorControl->iListBox->ItemHeight())- 2*(Rect().Height() / iIteratorControl->iListBox->ItemHeight()) );
				iIteratorControl->SetRect( TRect(0, titleHeight, Rect().Width(), Rect().Height()) );
				iTitleLabel->SetRect( TRect(0, 0, Rect().Width(), titleHeight) );
				/*
				TInt itemHeight = iIteratorControl->iListBox->ItemHeight();
				itemHeight = 45;
				iIteratorControl->SetRect( TRect(0, itemHeight, Rect().Width(), Rect().Height()) );
				iTitleLabel->SetRect( TRect(0, 0, Rect().Width(), itemHeight) );
				*/
				}
			if(iBgContext)
				{
				iBgContext->SetRect(Rect());
				iBgContext->SetParentPos( PositionRelativeToScreen() );
				}
			}
		
		};
	
	LManagedPtr<CContainer> iContainer;
	LManagedPtr<CIteratorControlState> iIteratorControlState;
	
	TBuf8<128> iSearchText;
	
	void CSingaporeBusIteratorView::HandleCommandL( TInt aCommand )
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		switch ( aCommand )
			{
			default:
				AppUi()->HandleCommandL(aCommand);
				break;
			}
		}
	
	
	CSingaporeBusIteratorView()
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		}

	~CSingaporeBusIteratorView()
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		}

	TInt iId;
	void ConstructL(TInt aResId, TInt aId)
		{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
		BaseConstructL( aResId );
		iId = aId;
		iIteratorControlState = new (ELeave) CIteratorControlState;
		}

	TUid Id() const
		{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
		return TUid::Uid( iId );
		}
	
	virtual CEikListBox* CreateListBoxL() = 0;

	void DoActivateL( 
			const TVwsViewId& aPrevViewId,
			TUid aCustomMessageId,
			const TDesC8& /*aCustomMessage*/ )
		{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	if ( iContainer == NULL )
		{
		
		iContainer = new (ELeave) CContainer;
		iContainer->SetMopParent( this );
		iContainer->ConstructL( scalp::MakeFunctionL( scalp::Bind(&CSingaporeBusIteratorView<T>::CreateListBoxL, this) ), this );
		AppUi()->AddToStackL( *this, iContainer.Get() );
		}
	iSearchText.Copy(KNullDesC);
		}
	
	void SearchTextChanged(const TDesC& aBuf, MCoeControlObserver::TCoeEvent aEvent)
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		
		switch(aEvent)
			{
			case MCoeControlObserver::EEventRequestCancel:
				{
				
				T currentItem;
				TBool currentItemIsValid( iContainer->iIteratorControl->iListBox->CurrentItemIndex() != -1 && iContainer->iIteratorControl->GetItemL(iContainer->iIteratorControl->iListBox->CurrentItemIndex(), currentItem) );
				TInt topCurrentDiff = iContainer->iIteratorControl->iListBox->CurrentItemIndex() - iContainer->iIteratorControl->iListBox->TopItemIndex();
				
				iSearchText.Copy(aBuf);
				iContainer->iIteratorControl->Reset();
				
				if(currentItemIsValid)
					{
					TInt i;
					T item;
					for(i = 0 ; iContainer->iIteratorControl->GetItemL(i, item) && item != currentItem ; ++i);  	
					if(iContainer->iIteratorControl->GetItemL(i, item))
						{
						iContainer->iIteratorControl->iListBox->SetTopItemIndex(i + topCurrentDiff);
						iContainer->iIteratorControl->iListBox->SetCurrentItemIndex(i);
						iContainer->iIteratorControl->iListBox->ScrollToMakeItemVisible(i);
						}
					}
				}
				break;
			default:
				{
				iSearchText.Copy(aBuf);
				iContainer->iIteratorControl->Reset();
				}
				break;
			}
		}


	void DoDeactivate()
		{
	TFunTrace funTrace(__PRETTY_FUNCTION__);
	if ( iContainer != NULL )
		{
		AppUi()->RemoveFromViewStack( *this, iContainer.Get() );
		iContainer = NULL;
		}
		}

	void NotifyAzimuthChange()
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		if(!iContainer) return;
		CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();		
		if(doc->iPositioningStatus == CSingaporeBusDocument::PS_FOUND)
			{
			this->iContainer->iIteratorControl->iListBox->DrawDeferred();
			}
		}
	
	void NotifyPositionChange()
		{
		TFunTrace funTrace(__PRETTY_FUNCTION__);
		if(!iContainer) return;
		CSingaporeBusDocument* doc = (CSingaporeBusDocument*)CEikonEnv::Static()->EikAppUi()->Document();		
		if(doc->iPositioningStatus == CSingaporeBusDocument::PS_FOUND && !doc->iPositionTracking) // we do not want to re-order while we are in position tracking
			{
			iContainer->iIteratorControl->Reset();
			}
		}
	
		
	};

#endif // __SINGAPOREBUSITERATORSVIEW__
